package com.pwt.service;

import com.pwt.common.CustomException;
import com.pwt.common.ResultPage;
import com.pwt.entity.*;
import com.pwt.model.*;
import com.pwt.model.crustallus.*;
import com.pwt.model.what.OverviewModel;
import com.pwt.repository.*;
import com.pwt.security.utils.JWTUtils;
import com.pwt.utils.*;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author dw
 * @version 1.0.0
 * @date 2021/9/26
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class CrustalLusService {

    private WERTEVARRepository wertevarRepository;

    private SigmaUtil sigmaUtil;

    private AbilityLineRepository abilityLineRepository;

    private HierarchyRepository hierarchyRepository;

    private FilterUnitRepository filterUnitRepository;

    private FilterUnitService filterUnitService;

    private PowerModuleRepository powerModuleRepository;

    private JPAQueryFactory jpaQueryFactory;

    private RoleRepository roleRepository;

    private AbilityLineService abilityLineService;


    public CrustalLusService(WERTEVARRepository wertevarRepository, SigmaUtil sigmaUtil, AbilityLineRepository abilityLineRepository, HierarchyRepository hierarchyRepository, FilterUnitRepository filterUnitRepository, FilterUnitService filterUnitService, PowerModuleRepository powerModuleRepository, JPAQueryFactory jpaQueryFactory, RoleRepository roleRepository, AbilityLineService abilityLineService) {
        this.wertevarRepository = wertevarRepository;
        this.sigmaUtil = sigmaUtil;
        this.abilityLineRepository = abilityLineRepository;
        this.hierarchyRepository = hierarchyRepository;
        this.filterUnitRepository = filterUnitRepository;
        this.filterUnitService = filterUnitService;
        this.powerModuleRepository = powerModuleRepository;
        this.jpaQueryFactory = jpaQueryFactory;
        this.roleRepository = roleRepository;
        this.abilityLineService = abilityLineService;
    }

    public LusHeaderModel getLusHeader(String k0053 , Integer k1000, Integer k0010, String startTime, String endTime){
        LusHeaderModel lusHeaderModel= this.wertevarRepository.getLusHeader(k0053,k1000,k0010,startTime, endTime);
        if(lusHeaderModel == null) return null;
        List<ParameterModel> list = this.wertevarRepository.getCharacteristicsInHeader(k0053,k1000,k0010);
        lusHeaderModel.setList(list);
        return lusHeaderModel;
    }

    public LusModel<OverviewModel> getOverViewValueChart(String k0053 , Integer k1000, Integer k0010,String startTime, String endTime, Integer page, Integer limit){
        LusHeaderModel headerModel= this.wertevarRepository.getLusHeader(k0053,k1000,k0010, startTime,  endTime);
        ResultPage<OverviewModel> pageResult = this.wertevarRepository.getCharacteristicsSigmaByOrderId( k0053 , k1000,  k0010, startTime, endTime ,page,  limit);
        List<OverviewModel> list = (List<OverviewModel>) pageResult.getData();
        for (int i = 0; i < list.size(); i++) {
            if(list.get(i) != null){
                if(list.get(i).getK2110() == null || list.get(i).getK2111() == null) continue;
                List<Double> listValue = this.wertevarRepository.getTestValue(k0053,list.get(i).getK1000(),list.get(i).getK2000(),k0010,startTime,endTime);
                if(listValue != null && listValue.size() > 0){
                    Double avg = MathUtil.avg(listValue);
                    list.get(i).setAvg(avg);
                    list.get(i).setN(listValue.size());

                    Double down = list.get(i).getK2110();
                    Double up = list.get(i).getK2111();
                    Double sigma = sigmaUtil.getSigma(listValue,avg);
                    Double T = up - down;

                    list.get(i).setSixSigma(DoubleUtils.retain2(6*sigma));
                    //cp
                    Double cp = MathUtil.divDouble(T,6*sigma);
                    list.get(i).setCp(cp);
                    Double cpu = MathUtil.divDouble((up - avg) , 3*sigma);
                    cpu = DoubleUtils.retain2(cpu);
                    Double cpl = MathUtil.divDouble((avg - down) , 3*sigma);
                    cpl = DoubleUtils.retain2(cpl);
                    //cpk
                    list.get(i).setCpk(Math.min(cpu,cpl));
                    // 判断状态  产品是否合格
                    if(listValue == null || listValue.size() < 1 ){
                        list.get(i).setStatus(3);
                    }else{
                        if(list.get(i).getCp() >= list.get(i).getCpTarget()
                                && list.get(i).getCpk() >= list.get(i).getCpkTarget()){
                            if(listValue.size() > 40){
                                list.get(i).setStatus(1);
                            }else{
                                list.get(i).setStatus(2);
                            }
                        }else{
                            list.get(i).setStatus(3);
                        }
                    }
                }

            }
        }

        LusModel<OverviewModel> lusModel = new LusModel();
        lusModel.setLusHeaderModel(headerModel);
        lusModel.setResultPage(pageResult);
        return lusModel;
    }


    public ChartModel  getOrderList(Integer k1000, Short k2000, Integer k0010, String k0053,String startTime,String endTime) throws CustomException {
        ChartModel acceptanceLimit = sigmaUtil.getAcceptanceLimit(k1000, k2000);
        List<ChartValueModel> chartList = this.wertevarRepository.getOrderList(k1000,k2000,k0010,k0053,startTime,endTime);
        if(chartList != null && chartList.size() > 0 ){
            acceptanceLimit.setPartId(chartList.get(0).getK1000());
            acceptanceLimit.setPart(chartList.get(0).getK1002());
        }
        acceptanceLimit.setList(chartList);
        List list = new ArrayList();
        for (int i=0;i<chartList.size();i++) {
            List<Object> child = new ArrayList<>();
            if(chartList.get(i) != null){
                child.add(i);
                child.add(chartList.get(i).getK0001());
            }
            list.add(child);
        }
        acceptanceLimit.setCurveList(list);
        return acceptanceLimit;
    };


    public List<BoxModel>  getBoxList(Integer k1000,Integer k2000, Integer k0010, String k0053,String startTime,String endTime){
        List<BoxModel> list = this.wertevarRepository.getBoxCharacteristics(k0053,k1000,k2000,k0010, startTime, endTime);
        for (BoxModel box:list) {
            List<Double> listValue = this.wertevarRepository.getTestValue(k0053,box.getK1000(), box.getK2000(), k0010,startTime,endTime);
            box.setValues(listValue);
            BoxModel plots = BoxUtils.getBoxPlots(listValue);
            if(plots != null){
                box.setQ1(plots.getQ1());
                box.setQ2(plots.getQ2());
                box.setQ3(plots.getQ3());
                box.setMin(plots.getMin());
                box.setMax(plots.getMax());
            }
        }
        return list;
    }


    /**
     *
     * @param id
     * @param filterId k2005  被测参数级别
     * @param startTime
     * @param endTime
     * @return
     * @throws CustomException
     */
    public  List<CrustalLusModel>  getCrustalLusPage(String id,String filterId,String startTime,String endTime) throws CustomException {
        String filters = null;
        if(filters != null && !filters.equals("")){
            FilterUnit filter = this.filterUnitRepository.findById(filterId).orElse(null);
            if(filter != null){
                filters = filter.getImportance();
            }
        }
        String username = JWTUtils.getToken().getUsername();
        Set<Role> roles = roleRepository.findByUsername(username);
        QRoleMachine qRoleMachine = QRoleMachine.roleMachine;
        QMASCHINE qMachine = QMASCHINE.mASCHINE;
        //用户配置的所有机器id
        HashSet<Integer> set = new HashSet<>();
        for (Role r:roles) {
            List<Integer> maschineList = jpaQueryFactory.select(qMachine.mAMASCHINE).from(qRoleMachine).leftJoin(qMachine).on(qRoleMachine.machineId.eq(qMachine.mAMASCHINE))
                    .where(qRoleMachine.roleId.eq(r.getId())).fetch();
            set.addAll(maschineList);
        }
        //主页树形
        List<TreeModel> treeList= null;

        if(id == null){
            //用户配置所看的机器
            treeList= abilityLineService.getHierarchySelect();
        }else {
            List<Hierarchy> hList= this.hierarchyRepository.findByAbilityLineId(id);
            treeList = new ArrayList<>();
            if(hList != null){
                for (Hierarchy hi:hList) {
                    if(hi.getPid() == null){
                        TreeModel treeModel = new TreeModel();
                        treeModel.setId(hi.getNumber());
                        treeModel.setName(hi.getName());
                        treeModel.setChildren(getListById(hi.getId(),hList));
                        treeList.add(treeModel);
                    }
                }
            }
        }

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        List<CrustalLusModel> cruList = new ArrayList<>();
        if(treeList != null && treeList.size() > 0 ){
            for (TreeModel tree:treeList) {
                CrustalLusModel crustalLusModel = new CrustalLusModel();
                crustalLusModel.setId(tree.getId());
                crustalLusModel.setName(tree.getName());
                cruList.add(crustalLusModel);
                if(tree != null && tree.getChildren() != null && tree.getChildren().size() > 0 ){
                    for (TreeModel two:tree.getChildren()) {
                        if(two != null){
                            CrustalLusModel crustalLus = new CrustalLusModel();
                            crustalLus.setId(two.getId());
                            crustalLus.setName(two.getName());
                            List<List<OrderModel>> total = new ArrayList<>();
                            List<Map<String,Object>> k1000List = this.powerModuleRepository.queryK1000GroupBy(filters,two.getId(),startTime,endTime);
                            if(k1000List != null && k1000List.size() > 0 ){
                                for(Map map:k1000List){
                                    Integer k1000 = null;
                                    if(!map.containsKey("k1000") || map.get("k1000") == null) continue;
                                    else k1000 = Integer.parseInt(map.get("k1000").toString());
                                    List<OrderModel> orderList = this.powerModuleRepository.queryOrder(filters,two.getId(),k1000,startTime,endTime);
//                                    try {
//                                        ShiftModel shiftModel = CommonUtils.getNowClass(new Date());
//                                        if(dateFormat.parse(endTime).getTime() >= shiftModel.getStartTime().getTime()){
//                                            List<OrderModel> newOrder =  this.wertevarRepository.getOrderListNew( filters,two.getId(),k1000,dateFormat.format(shiftModel.getStartTime()),dateFormat.format(shiftModel.getEndTime()));
//                                            orderList.addAll(newOrder);
//                                        }
//                                    } catch (ParseException e) {
//                                        e.printStackTrace();
//                                    }
                                    total.add(orderList);
                                }
                            }
                            crustalLus.setOrderList(total);
                            cruList.add(crustalLus);
                        }
                    }
                }
            }

        }
        return cruList;
    }

    public List<TreeModel>  getListById(String id, List<Hierarchy> list){
        List<TreeModel>  treeList = new ArrayList<>();
        if(list != null && list.size() > 0 ){
            for (Hierarchy hi:list) {
                if(id.equals(hi.getPid())){
                    TreeModel treeModel = new TreeModel();
                    treeModel.setId(hi.getNumber());
                    treeModel.setName(hi.getName());
                    treeModel.setChildren(getListById(hi.getId(),list));
                    treeList.add(treeModel);
                }
            }
        }
        return treeList;
    }

    //获取用户能力页面配置的  工序和机器
    public List<TreeModel> getAbilityTreeList(String abilityId){
        //主页树形
        List<TreeModel> treeList= null;

        if(abilityId == null){
            //用户配置所看的机器
            treeList= abilityLineService.getHierarchySelect();
        }else {
            List<Hierarchy> hList= this.hierarchyRepository.findByAbilityLineId(abilityId);
            treeList = new ArrayList<>();
            if(hList != null){
                for (Hierarchy hi:hList) {
                    if(hi.getPid() == null){
                        TreeModel treeModel = new TreeModel();
                        treeModel.setId(hi.getNumber());
                        treeModel.setName(hi.getName());
                        treeModel.setChildren(getListById(hi.getId(),hList));
                        treeList.add(treeModel);
                    }
                }
            }
        }
        return treeList;
    }

//    public List<GroupModel> getCrustalLusPruefer(String abilityId, String filterId, String startTime, String endTime){
//        String filters = null;
//        if(filters != null && !filters.equals("")){
//            FilterUnit filter = this.filterUnitRepository.findById(filterId).orElse(null);
//            if(filter != null){
//                filters = filter.getImportance();
//            }
//        }
//        List<TreeModel> treeList= getAbilityTreeList(abilityId);
//        Set<Integer> process = new HashSet<>();
//        Set<Integer> machine = new HashSet<>();
//        if(treeList != null){
//            for (TreeModel tree:treeList) {
//                process.add(tree.getId());
//                if(tree != null && tree.getChildren() != null && tree.getChildren().size() > 0 ){
//                    for (TreeModel twoTree:tree.getChildren()) {
//                        machine.add(twoTree.getId());
//                    }
//                }
//            }
//        }
//
//        List<GroupModel> result = new ArrayList<>();
//        List<GroupModel> groupList = this.wertevarRepository.getPrueferGroupModerList(filters,machine,startTime,endTime);
//        for (GroupModel group: groupList) {
//            GroupModel resultGroup  = selectGroupList(group,filters,machine,null,startTime,endTime);
//            result.add(resultGroup);
//        }
//        return result;
//    };

    public List<GroupModel> getCrustalLusMachine(String filterId,String abilityId ,String startTime, String endTime){
        String filters = null;
        if(filters != null && !filters.equals("")){
            FilterUnit filter = this.filterUnitRepository.findById(filterId).orElse(null);
            if(filter != null){
                filters = filter.getImportance();
            }
        }
        List<TreeModel> treeList= getAbilityTreeList(abilityId);
        Set<Integer> machine = new HashSet<>();
        if(treeList != null){
            for (TreeModel tree:treeList) {
                if(tree != null && tree.getChildren() != null && tree.getChildren().size() > 0 ){
                    for (TreeModel twoTree:tree.getChildren()) {
                        machine.add(twoTree.getId());
                    }
                }
            }
        }

        return this.powerModuleRepository.queryGroupByMaschine(machine,null,startTime,endTime);


        //List<GroupModel> groupList = this.wertevarRepository.getMachineGroupModerList(filters,machine,startTime,endTime);
//        for (GroupModel group: groupList) {
//            Set<Integer> set = new HashSet<>();
//            set.add(group.getId());
//            GroupModel resultGroup  = selectGroupList(group,filters,set,null,startTime,endTime);
//            result.add(resultGroup);
//        }
//        return result;

    };

    public List<GroupModel> getCrustalLusPart( String filterId, Integer machineId, String startTime, String endTime){

//        String filters = null;
//        if(filters != null && !filters.equals("")){
//            FilterUnit filter = this.filterUnitRepository.findById(filterId).orElse(null);
//            if(filter != null){
//                filters = filter.getImportance();
//            }
//        }
        Set<Integer> set = new HashSet<>();
        set.add(machineId);
        return this.powerModuleRepository.queryGroupByPart(set,null,startTime,endTime);

//        result.addAll(orderList);
//        List<GroupModel> groupList = this.wertevarRepository.getPartGroupModerList(filters,machineId,startTime,endTime);
//        for (GroupModel group: groupList) {
//            GroupModel resultGroup  = selectGroupList(group,filters,set,group.getId(),startTime,endTime);
//            result.add(resultGroup);
//        }
//        return result;

    };


    public GroupModel  selectGroupList(GroupModel group,String filters, Set<Integer> machineIds, Integer partId,String startTime, String endTime){
        List<OverviewModel>  characterList= this.wertevarRepository.getCharacteristicsByProcessAndMachine( filters , machineIds,  partId, startTime,  endTime);
        if(characterList != null && characterList.size() > 0 ){
            for (OverviewModel character:characterList) {
                if(character.getK2110() == null || character.getK2111() == null) continue;
                //根据被测参数 获取 测量值
                List<Double> values = this.wertevarRepository.getValueByProcessAndMachine(filters,machineIds,partId, startTime, endTime);
                Double avg = 0.00D;
                for (Double d:values) {
                    avg = avg+d;
                }
                avg = avg/values.size();

                Double down = character.getK2110();
                Double up = character.getK2111();
                Double sigma = sigmaUtil.getSigma(values,avg);
                Double T = up - down;

                //cp
                Double  cp= MathUtil.divDouble(T,6*sigma);
                cp = DoubleUtils.retain2(cp);
                Double cpu = MathUtil.divDouble((up - avg) , 3*sigma);
                cpu = DoubleUtils.retain2(cpu);
                Double cpl = MathUtil.divDouble((avg - down),3*sigma);
                cpl = DoubleUtils.retain2(cpl);
                //cpk
                Double cpk = Math.min(cpu,cpl);
                // 判断状态  产品是否合格

                if(cp >= character.getCpTarget()
                        && cpk >= character.getCpkTarget()){
                    if(values != null && values.size() <= 40 ){
                        group.setHasQualified(group.getHasQualified()+1);
                    }else{
                        group.setQualified(group.getQualified()+1);
                    }
                }else{
                    group.setDisqualification(group.getDisqualification()+1);
                }

            }
//            group.setQualifiedRate(DoubleUtils.retainPercent2 ((double) (group.getQualified()/characterList.size())));
//            group.setHasQualifiedRate(DoubleUtils.retainPercent2 ((double) (group.getHasQualified()/characterList.size())));
//            group.setDisqualificationRate(DoubleUtils.retainPercent2 ((double) (group.getDisqualification()/characterList.size())));
        }


        return group;
    }
}
